home *** CD-ROM | disk | FTP | other *** search
Wrap
// // BEGIN FLOCK GPL // // Copyright Flock Inc. 2005-2007 // http://flock.com // // This file may be used under the terms of of the // GNU General Public License Version 2 or later (the "GPL"), // http://www.gnu.org/licenses/gpl.html // // Software distributed under the License is distributed on an "AS IS" basis, // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License // for the specific language governing rights and limitations under the // License. // // END FLOCK GPL // const CLASS_ID = Components.ID("{C711A35C-8949-4D01-9676-47E71F1A78F4}"); const CLASS_NAME = "Flock Results Search Module"; const CONTRACT_ID = "@flock.com/flock-search-flock;1"; const flockISearchService = Components.interfaces.flockISearchService; const FLOCK_NS = "http://flock.com/rdf#"; const NC_NS = "http://home.netscape.com/NC-rdf#"; const RDFCU = Components.classes["@mozilla.org/rdf/container-utils;1"].getService(Components.interfaces.nsIRDFContainerUtils); const RDFS = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService); function flockSearchAPIFlock() { this._favService = Components.classes["@mozilla.org/rdf/datasource;1?name=flock-favorites"].getService(Components.interfaces.nsIRDFDataSource); this._logger = Components.classes["@flock.com/logger;1"].createInstance(Components.interfaces.flockILogger); this._logger.init("search"); var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService); var bundle = sbs.createBundle("chrome://flock/locale/search/search.properties"); this.serviceName = bundle.GetStringFromName("flock.search.api.flock"); }; flockSearchAPIFlock.prototype = { _searchListener: null, _maxResults: null, _searchesOutstanding: null, _resultsBookmarks: null, _resultsHistory: null, _currentQuery: null, RDFS: null, shortName: "flock", icon: "rdf:http://flock.com/rdf#icon", ref: "urn:flock:search:results", mDS: null, fullResultsUrl: "flock://search/?query=", search: function(aQuery, aNumResults, aListener, aDatasource) { this._searchListener = aListener; this._maxResults = aNumResults; this._currentQuery = aQuery; // get references to the services we use var searchService = Components.classes["@flock.com/lucene/flockLucene;1"].getService(Components.interfaces.flockILucene); this.RDFS = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService); var prefService = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch); // save a ref to the ds passed in this.mDS = aDatasource; var normalizedQuery = this.normalizeQuery(aQuery); this._logger.debug("query: \"" + aQuery + "\" => \"" + normalizedQuery + "\""); var showHistory = prefService.getBoolPref("flock.search.flyout.showHistory") && prefService.getBoolPref("flock.service.indexer.indexWebHistory"); // clear results this._resultsBookmarks = []; this._resultsHistory = []; // start the searchs if (showHistory) { this._searchesOutstanding = 2; searchService.search(normalizedQuery, "bookmark", this._maxResults, this); searchService.search(normalizedQuery, "history", this._maxResults, this); } else { this._searchesOutstanding = 1; searchService.search(normalizedQuery, "bookmark", this._maxResults, this); } }, normalizeQuery: function(input) { var output; var in_quotes = false; // strip leading spaces while (input.length && input[0]==" ") { // chop off the first character input = input.substr(1); } // Convert to lowercase for the wildcard search input = input.toLowerCase(); // add leading plus output = "+"; while (input.length) { if (input[0] == "\"") { if (in_quotes) { in_quotes = false; } else { in_quotes = true; // FIXME: remove spaces from the start of quoted strings } } // escape special chars if ("&|!(){}[]^~*?:\\".indexOf(input[0]) >= 0) { output = output + "\\"; } output = output + input[0]; if (!in_quotes && input[0] == " " && input.length > 1) { // put a plus before every word output = output + "+"; } input = input.substr(1); } // remove trailing spaces var removed_spaces = false; while (output.length > 0 && output[output.length - 1] == " ") { output = output.substr(0, output.length - 1); removed_spaces = true; } // if we're in a quoted string we should close that if (in_quotes) { output = output + "\""; } // if theres an incomplete word if ((!removed_spaces) && (output[output.length - 1] != "\"")) { // search for partial matches output = output + "*"; } return output; }, // flockILuceneListener onSearchComplete: function(aNumResults, aDataSource) { this._logger.debug("onSearchComplete: hits: " + aNumResults); if (aNumResults > 0) { var root = this.RDFS.GetResource("urn:flock:search:results"); var container = Components.classes["@mozilla.org/rdf/container;1"].createInstance(Components.interfaces.nsIRDFContainer); try { container.Init(aDataSource, root); } catch (ex) {} var results = container.GetElements(); while (results.hasMoreElements()) { var result = results.getNext(); result.QueryInterface(Components.interfaces.nsIRDFResource); var uri = result.ValueUTF8; var url = aDataSource.GetTarget(result, this.RDFS.GetResource(FLOCK_NS + "URL"), true).QueryInterface(Components.interfaces.nsIRDFLiteral).Value; var type = aDataSource.GetTarget(result, this.RDFS.GetResource(FLOCK_NS + "type"), true).QueryInterface(Components.interfaces.nsIRDFLiteral).Value; var title = aDataSource.GetTarget(result, this.RDFS.GetResource("http://home.netscape.com/NC-rdf#Name"), true).QueryInterface(Components.interfaces.nsIRDFLiteral).Value; this._logger.debug("foundResults: " + type + " " + uri); switch(type) { case "bookmark": this._resultsBookmarks.push([url, title]); break; case "history": this._resultsHistory.push([url, title]); break; } } } this._searchesOutstanding--; if (this._searchesOutstanding == 0) { this._returnResults(); } }, _returnResults: function() { this._logger.debug("_returnResults"); var resultSet = this.mDS; var resultSetRoot = this.RDFS.GetResource("urn:flock:search:results"); var rootContainer = RDFCU.MakeSeq(resultSet, resultSetRoot); var c; var urlHash = {}; var url; var title; var favicon; var result; var resultCount = 0; // return bookmark results for (c = 0; c < this._resultsBookmarks.length && resultCount < this._maxResults; c++) { url = this._resultsBookmarks[c][0]; title = this._resultsBookmarks[c][1]; favicon = "chrome://browser/skin/flock/search/documentIcon16.png"; infoicon = "chrome://browser/skin/flock/common/star16.png"; // skip duplicate bookmarks (online bookmarks) if (urlHash[url] == true) { continue; } urlHash[url] = true; result = this.RDFS.GetAnonymousResource(); rootContainer.AppendElement(result); resultSet.Assert(result, this.RDFS.GetResource("http://home.netscape.com/NC-rdf#URL"), this.RDFS.GetLiteral(url), true); resultSet.Assert(result, this.RDFS.GetResource("http://home.netscape.com/NC-rdf#Name"), this.RDFS.GetLiteral(title), true); resultSet.Assert(result, this.RDFS.GetResource("http://home.netscape.com/NC-rdf#favicon"), this.RDFS.GetLiteral(favicon), true); resultSet.Assert(result, this.RDFS.GetResource(FLOCK_NS + "infoicon"), this.RDFS.GetLiteral(infoicon), true); resultCount++; } // fill in history results for (c = 0; c < this._resultsHistory.length && resultCount < this._maxResults; c++) { url = this._resultsHistory[c][0]; title = this._resultsHistory[c][1]; favicon = "chrome://browser/skin/flock/search/documentIcon16.png"; // skip history results that have already been returned as bookmarks if (urlHash[url] == true) { continue; } result = this.RDFS.GetAnonymousResource(); rootContainer.AppendElement(result); resultSet.Assert(result, this.RDFS.GetResource("http://home.netscape.com/NC-rdf#URL"), this.RDFS.GetLiteral(url), true); resultSet.Assert(result, this.RDFS.GetResource("http://home.netscape.com/NC-rdf#Name"), this.RDFS.GetLiteral(title), true); resultSet.Assert(result, this.RDFS.GetResource("http://home.netscape.com/NC-rdf#favicon"), this.RDFS.GetLiteral(favicon), true); resultCount++; } this._searchListener.foundResults(resultCount, resultSet, this.shortName, this._currentQuery); // JMC - Trying to fix leak of this listener this._searchListener = null; }, // nsIClassInfo getInterfaces: function(aCount) { var interfaces = [Components.interfaces.flockISearchService, Components.interfaces.nsIClassInfo, Components.interfaces.flockILuceneListener]; aCount.value = interfaces.length; return interfaces; }, // nsIClassInfo getHelperForLanguage: function(aLanguage) { return null; }, // nsIClassInfo contractID: CONTRACT_ID, // nsIClassInfo classDescription: CLASS_NAME, // nsIClassInfo classID: CLASS_ID, // nsIClassInfo implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT, // nsIClassInfo flags: Components.interfaces.nsIClassInfo.SINGLETON, // nsISupports QueryInterface: function(aIID) { if (!aIID.equals(Components.interfaces.nsISupports) && !aIID.equals(Components.interfaces.flockISearchService) && !aIID.equals(Components.interfaces.nsIClassInfo) && !aIID.equals(Components.interfaces.flockILuceneListener)) throw Components.results.NS_ERROR_NO_INTERFACE; return this; } }; /****************************************************************************** * XPCOM Functions for construction and registration ******************************************************************************/ var Module = { _firstTime: true, registerSelf: function(aCompMgr, aFileSpec, aLocation, aType) { if (this._firstTime) { this._firstTime = false; throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN; } aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar); aCompMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME, CONTRACT_ID, aFileSpec, aLocation, aType); // register search provider var catmgr = Components.classes["@mozilla.org/categorymanager;1"] .getService(Components.interfaces.nsICategoryManager); catmgr.addCategoryEntry("flockISearchService", "flock", CONTRACT_ID, true, true); }, unregisterSelf: function(aCompMgr, aLocation, aType) { aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar); aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation); }, getClassObject: function(aCompMgr, aCID, aIID) { if (!aIID.equals(Components.interfaces.nsIFactory)) throw Components.results.NS_ERROR_NOT_IMPLEMENTED; if (aCID.equals(CLASS_ID)) return Factory; throw Components.results.NS_ERROR_NO_INTERFACE; }, canUnload: function(aCompMgr) { return true; } }; var Factory = { createInstance: function(aOuter, aIID) { if (aOuter != null) throw Components.results.NS_ERROR_NO_AGGREGATION; return (new flockSearchAPIFlock()).QueryInterface(aIID); } }; function NSGetModule(aCompMgr, aFileSpec) { return Module; }